package org.web.base.domain.helper;

import lombok.NonNull;
import lombok.SneakyThrows;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.web.base.domain.ResultDO;
import org.web.base.domain.exception.ResultMessageEnum;
import org.web.base.domain.exception.ServiceException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SuppressWarnings("ALL")
public class ResultHelper {


    public static void buildResultDOByResultMessageEnum(ResultDO resultDO, @NonNull ResultMessageEnum resultMessageEnum, String message, Map extendsDomain) {
        if (ResultMessageEnum.SUCCESS == resultMessageEnum) {
            resultDO.setSuccess(true);
        } else {
            resultDO.setSuccess(false);
        }
        if (StringUtils.isNotBlank(message)) {
            resultDO.setMessage(message);
        } else {
            resultDO.setMessage(resultMessageEnum.getMessage());
        }
        resultDO.setCode(resultMessageEnum.getCode());
        resultDO.setExtendsDomain(extendsDomain);
    }

    public static <T> ResultDO<T> buildResultDOByResultMessageEnum(@NonNull ResultMessageEnum resultMessageEnum, String message, Map extendsDomain) {
        ResultDO resultDO = new ResultDO(false);
        if (ResultMessageEnum.SUCCESS == resultMessageEnum) {
            resultDO.setSuccess(true);
        }
        if (StringUtils.isNotBlank(message)) {
            resultDO.setMessage(message);
        } else {
            resultDO.setMessage(resultMessageEnum.getMessage());
        }
        resultDO.setCode(resultMessageEnum.getCode());
        resultDO.setExtendsDomain(extendsDomain);
        return resultDO;
    }

    @SneakyThrows
    public static <T, Y> ResultDO<List<T>> buildResultDOByResultDO(ResultDO<List<Y>> resultDO, Class<T> tClass) {
        ResultDO<List<T>> destResult = new ResultDO();
        BeanUtils.copyProperties(destResult, resultDO);
        if (ObjectUtils.isNotEmpty(resultDO.getDomain())) {
            List<T> list = new ArrayList<>(resultDO.getDomain().size());
            destResult.setDomain(list);
            for (Object obj : resultDO.getDomain()) {
                T dest = tClass.newInstance();
                BeanUtils.copyProperties(dest, obj);
                list.add(dest);
            }
        } else {
            destResult.setDomain(new ArrayList<>());
        }
        return destResult;
    }

    public static <T> ResultDO<T> buildResultDOByResultMessageEnum(ResultMessageEnum resultMessageEnum, String message) {
        return buildResultDOByResultMessageEnum(resultMessageEnum, message, null);
    }


    public static <T> ResultDO<T> buildResultDOByResultMessageEnum(ResultMessageEnum resultMessageEnum, Map extendsDomain) {
        return buildResultDOByResultMessageEnum(resultMessageEnum, null, extendsDomain);
    }

    public static <T> ResultDO<T> buildResultDOByResultMessageEnum(ResultMessageEnum resultMessageEnum) {
        return buildResultDOByResultMessageEnum(resultMessageEnum, null, null);
    }

    public static <T> ResultDO<T> buildResultDOByException(Exception e, T domain, Object obj) {
        Map<String, Object> extendsDescriptions = new HashMap<>();
        extendsDescriptions.put("default", obj);
        return buildResultDOByException(e, domain, extendsDescriptions);
    }

    /***
     * Payattention there are some same key name, between serviceException.getextendsDescriptions() and input extendsDescription.
     * */
    public static <T> ResultDO<T> buildResultDOByException(Exception e, T domain, Map extendsDescription) {
        ResultDO resultDO = new ResultDO(false);
        if (extendsDescription != null) {
            resultDO.setExtendsDomain(extendsDescription);
        }
        if (e instanceof ServiceException) {
            ServiceException serviceException = (ServiceException) e;
            resultDO.setCode(serviceException.getErrorCode());
            if (StringUtils.isNotBlank(serviceException.getMessage())) {
                resultDO.setMessage(serviceException.getMessage());
            } else if (StringUtils.isNotBlank(serviceException.getDescription())) {
                resultDO.setMessage(serviceException.getDescription());
            }
            if (ObjectUtils.isNotEmpty(serviceException.getExtendsValues())) {
                resultDO.getExtendsDomain().putAll(serviceException.getExtendsValues());
            }
            if (ObjectUtils.isNotEmpty(serviceException.getErrorList())) {
                resultDO.withErrorInfo(serviceException.getErrorList());
            }

        } else {
            resultDO.setCode(ResultMessageEnum.SYSTEM_ERROR.getCode());
            resultDO.setMessage(ServiceExceptionHelper.getExceptionInfo(e));
        }
        resultDO.setDomain(domain);
        return resultDO;
    }

    public static <T> ResultDO<T> buildResultDOByException(Exception e) {
        return buildResultDOByException(e, null, null);
    }

    public static <T> ResultDO<T> buildResultDOByException(Exception e, T domain) {
        return buildResultDOByException(e, domain, null);
    }

}
